package com.yazi.mxz.person.controller.shop;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.myframework.smhj.common.exception.MyException;
import com.myframework.smhj.common.tool.CommonUtil;
import com.myframework.smhj.common.tool.DateUtil;
import com.myframework.smhj.jackson.result.ObjectResult;
import com.myframework.smhj.jackson.result.StatusResult;
import com.yazi.mxz.common.ComSetting;
import com.yazi.mxz.common.MyUtil;
import com.yazi.mxz.common.entity.beans.Member;
import com.yazi.mxz.common.entity.beans.Sms;
import com.yazi.mxz.common.entity.constant.RegExp;
import com.yazi.mxz.common.entity.enums.SettingId;
import com.yazi.mxz.common.entity.enums.SmsType;
import com.yazi.mxz.common.service.MemberService;
import com.yazi.mxz.common.service.SmsService;

@Controller("shop-memberController")
@RequestMapping("/shop/member")
public class MemberController extends BaseController {
	private static Logger log = LoggerFactory.getLogger(MemberController.class);
	private static final String SESSION_KEY_SMS = "smsCaptcha";
	
	@Resource
	MemberService memberService;
	@Resource
	SmsService smsService;
	
	@RequestMapping("/notExists/json")
	@ResponseBody
	public Map<String, Object> notExistsJson(String mobile) {
		debug(log, "检查用户是否存在");
		Map<String, Object> map = new HashMap<String, Object>();
		Member member = null;
		try {
			member = memberService.oneByAccountName(mobile);
			if (null == member) {
				map.put("ok", "");
			} else {
				map.put("error", "号码已经被使用");
			}
		} catch (Exception e) {
			error(log, e, "检查用户是否存在时异常");
			map.put("error", e.getMessage());
		}
	
		return map;
	}
	
	@RequestMapping("/register")
	public String register(Model model) {
		debug(log, "进入新会员注册页面");
		
		Captcha cap = getSmsCaptcha();
		if (null != cap) {
			// 下次发送剩余时间
			model.addAttribute("remainTime", getSmsLag() - (DateUtil.getTimeStamp() - cap.getTimestamp()));
		}
		return "shop/member_register";
	}
	
	@RequestMapping("/registerDo/json")
	@ResponseBody
	public StatusResult registerDoJson(String mobile, String captcha) {
		debug(log, "提交注册");
		StatusResult jsonResult = new StatusResult();
		try {
			if (!checkSmsCaptcha(mobile, captcha)) {
				jsonResult.setErrorMessage("验证码无效");
				return jsonResult;
			}
			
			// TODO	用户名为“u” + 手机号码前3位 + 随机4个字符 + 手机号码后4位
			String userName = "u" + mobile.substring(0, 3) + CommonUtil.randomLN(4) + mobile.substring(7, mobile.length());
			String password = MyUtil.makePassword(8);
			
			// 注册
			Member member = new Member();
			member.setName(userName);
			member.setPassword(password);
			member.setMobile(mobile);
			member = memberService.add(member);
			
			// 发短信
			Sms sms = new Sms();
			sms.setType(SmsType.REGISTER_ACCOUNT.ordinal());
			sms.setToMobile(mobile);
			// TODO 用户名|密码|PIN码，格式固定
			sms.setParams(userName + "|" + password + "|" + member.getPin());
			smsService.add(sms);
			
			jsonResult.setOk();
		} catch (MyException e) {
			debug(log, e.getMessage());
			jsonResult.setFailMessage(e.getMessage());
		} catch (Exception e) {
			error(log, e, "用户注册异常");
			jsonResult.setErrorMessage("注册失败，请联系管理员");
		}
		return jsonResult;
	}
	
	@RequestMapping("/getCaptcha/json")
	@ResponseBody
	public ObjectResult<?> getCaptchaJson(String mobile) {
		debug(log, "获取手机验证码");
		ObjectResult<Long> jsonResult = new ObjectResult<Long>();
		try {
			if (!mobile.matches(RegExp.MOBILE)) {
				jsonResult.setFailMessage("手机号无效");
				return jsonResult;
			}
			Captcha cap = getSmsCaptcha();
			if (null != cap && (DateUtil.getTimeStamp() - cap.getTimestamp()) < getSmsLag()) {
				jsonResult.setFailMessage("操作太频繁");
				return jsonResult;
			}
			// 检查该手机是否被使用
			Member member = memberService.oneByAccountName(mobile);
			if (null != member) {
				jsonResult.setErrorMessage("手机号已被他人使用");
				return jsonResult;
			}
			
			// 发送短信验证码
			setCaptchaForMobile(mobile);
			
			jsonResult.setResult(getSmsLag());
			jsonResult.setOk();
		} catch (MyException e) {
			debug(log, e.getMessage());
			jsonResult.setFailMessage(e.getMessage());
		} catch (Exception e) {
			error(log, e, "短信验证码发送失败");
			jsonResult.setErrorMessage("操作失败，请联系管理员");
		}
		return jsonResult;
	}
	
	private Captcha getSmsCaptcha() {
		return (Captcha) getSession().getAttribute(SESSION_KEY_SMS);
	}
	
	private void removeSession(Object key) {
		getSession().removeAttribute(key);
	}
	
	private Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}
	
	/**
	 * 短信发送时间间隔
	 * @return
	 */
	private long getSmsLag() {
		return ComSetting.getLong(SettingId.SMS_LAG);
	}
	
	private void setCaptchaForMobile(String mobile) throws MyException {
		int captcha = MyUtil.makeCaptcha();
		debug(log, "发送短信验证码");
		
		Captcha sc = new Captcha();
		sc.setCaptcha(captcha + "");
		sc.setReceiver(mobile);
		getSession().setAttribute(SESSION_KEY_SMS, sc);
		
        
		// 发短信
		Sms sms = new Sms();
		sms.setType(SmsType.BIND_ACCOUNT.ordinal());
		sms.setToMobile(mobile);
		// TODO 验证码|有效时间(单位：分钟)，格式固定
		sms.setParams(captcha + "|" + ComSetting.getLong(SettingId.SMS_INDATE)/60000);
		smsService.add(sms);
	}
	
	/**
	 * 手机和验证码校验
	 * @param mobile
	 * @param captcha
	 * @return
	 */
	private boolean checkSmsCaptcha(String mobile, String captcha) {
		Captcha cap = getSmsCaptcha();
		// 没输入验证码、验证码不存在、手机号不一致或者超时
		if (null == captcha || null == cap || !mobile.equals(cap.getReceiver())
				|| (DateUtil.getTimeStamp() - cap.getTimestamp()) > ComSetting.getLong(SettingId.SMS_INDATE)) {
			return false;
		}
		
		// 输入不正确
		if (!captcha.equals(cap.getCaptcha())) {
			cap.setFail(cap.getFail() + 1);
			getSession().setAttribute(SESSION_KEY_SMS, cap);
			return false;
		}
		
		// 正确后再删
		removeSession(SESSION_KEY_SMS);
		// 即使输入正确，但错误次数达到上限同样作为验证失败
		// 因为可能是无数次错误输入尝试后碰巧命中，这种情况下不予通过
		if (cap.getFail() >= ComSetting.getLong(SettingId.SMS_BRAKE)) {
			return false;
		}
		
		return true; 
	}
	
	class Captcha {
		// 目标手机号或者邮箱
		private String receiver;
		// 验证码
		private String captcha;
		// 验证码生成时间
		private long timestamp = DateUtil.getTimeStamp();
		// 验证码输入错误次数
		private int fail = 0;
		
		public String getReceiver() {
			return receiver;
		}
		public void setReceiver(String receiver) {
			this.receiver = receiver;
		}
		public String getCaptcha() {
			return captcha;
		}
		public void setCaptcha(String captcha) {
			this.captcha = captcha;
		}
		public long getTimestamp() {
			return timestamp;
		}
		public void setTimestamp(long timestamp) {
			this.timestamp = timestamp;
		}
		public int getFail() {
			return fail;
		}
		public void setFail(int fail) {
			this.fail = fail;
		}
	}
	
}
